package com.main.activity;


//base
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import java.util.List;
import android.view.KeyEvent;
import android.content.Intent;
import android.content.Context;
import android.os.Environment;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
import org.json.JSONObject;
 
//unity
import com.unity3d.player.UnityPlayerActivity;
import com.unity3d.player.UnityPlayer;



import android.Manifest;
import android.content.pm.PackageManager;


import org.json.JSONObject;


//Il2cpp patch
import io.github.noodle1983.Boostrap;


//version
import com.main.Version;




import ${app_packagename}.R;

public class MainActivity extends UnityPlayerActivity {
    private String onBackPressedCallbackClassName;
    private String onBackPressedCallbackFunctionName;
    public Activity activity;


	public String getIl2cppPatchLibraryFilesPath()
	{
		String filePath = null;
		filePath = this.getFilesDir().getPath() ;
		return filePath;
	}
	
	public String getFilesPath( Context context )
	{
		String filePath = null;
		if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) 
		{
			//外部存储可用
			filePath = context.getExternalFilesDir(null).getPath();
		}
		else
		{
			//外部存储不可用
        filePath = context.getFilesDir().getPath() ;
		}
		return filePath;
	}

	public void WriteTextToFile(String filePath, String fileName, String text)
	{
		File file = new File(filePath, fileName);

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(text.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
	}


	public boolean ExistsFile(String filePath) {
		File file = new File(filePath);
        return file.exists();
    }
	
	/**
     * 删除单个文件
     * @param   filePath    被删除文件的文件名
     * @return 文件删除成功返回true，否则返回false
     */
    public boolean deleteFile(String filePath) {
    File file = new File(filePath);
        if (file.isFile() && file.exists()) {
        return file.delete();
        }
        return false;
    }

    /**
     * 删除文件夹以及目录下的文件
     * @param   filePath 被删除目录的文件路径
     * @return  目录删除成功返回true，否则返回false
     */
    public boolean deleteDirectory(String filePath) {
    boolean flag = false;
        //如果filePath不以文件分隔符结尾，自动添加文件分隔符
        if (!filePath.endsWith(File.separator)) {
            filePath = filePath + File.separator;
        }
        File dirFile = new File(filePath);
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        flag = true;
        File[] files = dirFile.listFiles();
        //遍历删除文件夹下的所有文件(包括子目录)
        for (int i = 0; i < files.length; i++) {
            if (files[i].isFile()) {
            //删除子文件
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag) break;
            } else {
            //删除子目录
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) break;
            }
        }
        if (!flag) return false;
        //删除当前空目录
        return dirFile.delete();
    }

    /**
     *  根据路径删除指定的目录或文件，无论存在与否
     *@param filePath  要删除的目录或文件
     *@return 删除成功返回 true，否则返回 false。
     */
    public boolean DeleteFolder(String filePath) {
    File file = new File(filePath);
        if (!file.exists()) {
            return false;
        } else {
            if (file.isFile()) {
            // 为文件时调用删除文件方法
                return deleteFile(filePath);
            } else {
            // 为目录时调用删除目录方法
                return deleteDirectory(filePath);
            }
        }
    }

	public String GetIl2cppPatchResourcePath()
	{
		return getFilesPath(this) + "/il2cpp_patch";
	}
	
	public String GetIl2cppPatchResourceCachePath()
	{
		return getFilesPath(this) + "/il2cpp_patch_cache";
	}
	
	public String GetIl2cppPatchPath()
	{
		return GetIl2cppPatchResourcePath() + "/patch";
	}
	
	public String GetIl2cppPatchCachePath()
	{
		return GetIl2cppPatchResourceCachePath() + "/patch";
	}
	
	public static String ReadTxtFile(String strFilePath)
    {
        String path = strFilePath;
        String content = ""; //文件内容字符串
            //打开文件
		File file = new File(path);
		//如果path是传递过来的参数，可以做一个非目录的判断
		if (file.isDirectory())
		{
			Log.d("TestFile", "The File doesn't not exist.");
		}
		else
		{
			try {
				FileInputStream instream = new FileInputStream(file);
				if (instream != null)
				{
					InputStreamReader inputreader = new InputStreamReader(instream);
					BufferedReader buffreader = new BufferedReader(inputreader);
					String line;
					//分行读取
					while (( line = buffreader.readLine()) != null) {
						content += line + "\n";
					}               
					instream.close();
				}
			}
			catch (java.io.FileNotFoundException e)
			{
				Log.d("TestFile", "The File doesn't not exist.");
			}
			catch (IOException e)
			{
				 Log.d("TestFile", e.getMessage());
			}
		}
		return content;
    }
	
	public void RenameFile(String srcPath, String destPath)
	{
		File src = new File(srcPath);
		if(!src.exists())
		{
			return;
		}
		
		src.renameTo(new File(destPath));
	}
	
	public class Il2cppPatchConfig
	{
		public String md5;
		public int version;
		public int min_app_version;
	}
	
	public Il2cppPatchConfig ParseIl2cppPatchConfig(String path)
	{
		String text = ReadTxtFile(path);
		if(text == null)
		{
			return null;
		}
		
		try {
            JSONObject jsonObject = new JSONObject(text);
			if(jsonObject == null)
			{
				return null;
			}
			
			Il2cppPatchConfig config = new Il2cppPatchConfig();
			config.md5 = jsonObject.getString("md5");
			config.version = jsonObject.getInt("version");
			config.min_app_version = jsonObject.getInt("min_app_version");
			return config;
        }
		catch (Exception e)
		{
            e.printStackTrace();
        }

		return null;
	}

	public static final String Il2cppPatchConfigName = "config.txt";
	public static Il2cppPatchConfig il2cppPatchConfig;
	
	public String GetIl2cppPatchMd5()
	{
		if(il2cppPatchConfig != null)
		{
			return il2cppPatchConfig.md5;
		}
		return null;
	}
	
	public boolean SaveIl2cppPatchConfig(String savePath, String md5, int version, int minAppVersion)
	{
		try
		{
            JSONObject jsonObject = new JSONObject();
			jsonObject.put("md5", md5);
			jsonObject.put("version", version);
			jsonObject.put("min_app_version", minAppVersion);
			
			WriteTextToFile(savePath, Il2cppPatchConfigName, jsonObject.toString());
			return true;
        }
		catch (Exception e)
		{
            e.printStackTrace();
        }
		
		return false;
	}
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
		
		//for il2cpp patch begin
		{
			if(isIl2cpp())
			{
				if(ExistsFile(GetIl2cppPatchResourceCachePath()))
				{
					Il2cppPatchConfig config = ParseIl2cppPatchConfig(GetIl2cppPatchResourceCachePath() + "/"+ Il2cppPatchConfigName);
					if(config == null)
					{
						DeleteFolder(GetIl2cppPatchResourceCachePath());
					}
					else
					{
						DeleteFolder(GetIl2cppPatchResourcePath());
						RenameFile(GetIl2cppPatchResourceCachePath(), GetIl2cppPatchResourcePath());
					}
				}
				
				if(ExistsFile(GetIl2cppPatchResourcePath()))
				{
					Il2cppPatchConfig config = ParseIl2cppPatchConfig(GetIl2cppPatchResourcePath() + "/"+ Il2cppPatchConfigName);
					if(config == null || config.version <= Version.version_number || config.min_app_version > Version.version_number)
					//if(config == null)
					{
						DeleteFolder(getFilesPath(this) + "/il2cpp");
						DeleteFolder(GetIl2cppPatchResourcePath());
					}
					else
					{
						//WriteTextToFile(getFilesPath(getApplication().getApplicationContext()), "test_files.txt", "this is test: " + GetIl2cppPatchPath());
        
						if(!ExistsFile(GetIl2cppPatchResourcePath() + "/used.txt"))
						{
							//WriteTextToFile(getFilesPath(getApplication().getApplicationContext()), "test_files2.txt", "this is test: " + GetIl2cppPatchPath());
        
							DeleteFolder(getFilesPath(this) + "/il2cpp");
							
							//WriteTextToFile(getFilesPath(getApplication().getApplicationContext()), "test_files_dir.txt", "this is test: " + GetIl2cppPatchPath());
        
							Boostrap.InitNativeLibBeforeUnityPlay(getIl2cppPatchLibraryFilesPath());
						
							//WriteTextToFile(getFilesPath(getApplication().getApplicationContext()), "test_files_dir1.1.txt", "this is test: " + GetIl2cppPatchPath());
        
							
							Boostrap.useDataDir(GetIl2cppPatchPath(), "");
							
							WriteTextToFile(GetIl2cppPatchResourcePath(), "used.txt", "true");
						}
						else
						{
							//WriteTextToFile(getFilesPath(getApplication().getApplicationContext()), "test_files_dir.1.2.txt", "this is test: " + GetIl2cppPatchPath());
        
							Boostrap.InitNativeLibBeforeUnityPlay(getIl2cppPatchLibraryFilesPath());
						
							//WriteTextToFile(getFilesPath(getApplication().getApplicationContext()), "test_files_dir1.3.txt", "this is test: " + GetIl2cppPatchPath());
						}
						
						
						
						//WriteTextToFile(getFilesPath(getApplication().getApplicationContext()), "test_files_dir3.txt", "this is test: " + GetIl2cppPatchPath());
        
						il2cppPatchConfig = config;
						Boostrap.start();
						
						//WriteTextToFile(getFilesPath(getApplication().getApplicationContext()), "test_files_dir4.txt", "this is test: " + GetIl2cppPatchPath());
        
					}
				}
			}
			else
			{
				DeleteFolder(getFilesPath(this) + "/il2cpp");
				DeleteFolder(GetIl2cppPatchResourceCachePath());
				DeleteFolder(GetIl2cppPatchResourcePath());
			}
		}
		//for il2cpp patch end
		
		
		super.onCreate(savedInstanceState);


        this.activity = this;
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
    }


    public String getChannel() {
        return getString(R.string.channel);
    }

    public void setOnBackPressedCallback(String className, String functionName) {
        this.onBackPressedCallbackClassName = className;
        this.onBackPressedCallbackFunctionName = functionName;
    }

    // 调用unity方法
    private void CallUnityMethod(String methodName, String msg)
    {
        UnityPlayer.UnitySendMessage("AndroidHelper", methodName, msg);
    }

    public int GetSDKInt()
    {
        return Build.VERSION.SDK_INT;
    }
	
	public boolean isIl2cpp()
    {
        return Version.is_il2cpp;
    }
	
	public int GetVersionNumber()
    {
        return Version.version_number;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        if(keyCode == KeyEvent.KEYCODE_BACK)
        {
            if(onBackPressedCallbackClassName != null && onBackPressedCallbackFunctionName != null)
            {
                UnityPlayer.UnitySendMessage(onBackPressedCallbackClassName, onBackPressedCallbackFunctionName, "");
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    public void onBackPressed() {
        super.onBackPressed();
//        Sdk.getInstance().exit(this.activity);
    }


}
